package huixue.cn.com.rxapp.widget.kline;

import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.widget.Scroller;

import java.util.ArrayList;

import huixue.cn.com.library.util.LogUtils;
import huixue.cn.com.rxapp.widget.data.StickData;
import huixue.cn.com.rxapp.widget.util.ColorUtil;
import huixue.cn.com.rxapp.widget.util.DrawUtils;
import huixue.cn.com.rxapp.widget.util.GridUtils;
import huixue.cn.com.rxapp.widget.util.IndexParseUtil;
import huixue.cn.com.rxapp.widget.util.LineUtil;

/**
 * Created by Administrator on 2018/8/14.
 */

public class KLineView extends ChartView{

    //烛形图加空白的宽度和烛形图宽度之比
    public static final float WIDTH_SCALE = 1.2f;
    //烛形图和右侧空白的宽度
    public float DEFUALT_WIDTH = 19;
    //K线所有数据
    private ArrayList<StickData> data;
    //K线展示的数据
    private ArrayList<StickData> showList;
    //一屏烛形图数量
    private int drawCount;
    //没两个烛形图x轴的距离
    private float candleXDistance;

    //当前画图偏移量（往右滑动之后）
    private int offset;
    //y轴最大值
    protected double yMax;
    //y轴最小值
    protected double yMin;

    protected float yUnit;
    protected float xUnit;

    /**
     * 计算手指滑动的距离
     */
    private float mLastX;
    private Scroller mScroller;

    /**
     * 最小的边界值
     */
    private int mMinScrollX;

    /**
     * 最大的边界值
     */
    private int mMaxScrollX;

    private VelocityTracker mVelocityTracker;

    /**
     * fling的最小阈值
     */
    private int mMinVelocity;

    /**
     * fling的最大速度
     */
    private int mMaxVelocity;

    public KLineView(Context context) {
        super(context);
    }

    public KLineView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        mVelocityTracker = VelocityTracker.obtain();


        mScroller = new Scroller(getContext());

        ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
        mMinVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
        mMaxVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void drawGrid(Canvas canvas) {
        GridUtils.drawGrid(canvas, mWidth, mainH);
        GridUtils.drawIndexGrid(canvas, indexStartY, mWidth, indexH);
    }

    /**
     * SMA5 SMA10 SMA20
     * @param canvas
     */
    @Override
    protected void drawLines(Canvas canvas) {
        if(data == null || data.size() == 0) return;
        float[] sma5 = new float[showList.size()];
        float[] sma10 = new float[showList.size()];
        float[] sma20 = new float[showList.size()];
        int size = showList.size();
        for (int i = 0; i < showList.size(); i++) {
            if(size > IndexParseUtil.START_SMA5)
                sma5[i] = (float) showList.get(i).getSma5();
            if(size > IndexParseUtil.START_SMA10)
                sma10[i] = (float) showList.get(i).getSma10();
            if(size > IndexParseUtil.START_SMA20)
                sma20[i] = (float) showList.get(i).getSma20();
        }
        DrawUtils.drawLineWithXOffset(canvas, sma5, DEFUALT_WIDTH, mainH, ColorUtil.COLOR_SMA5, (float) yMax, (float) yMin, DEFUALT_WIDTH / 2);
        DrawUtils.drawLineWithXOffset(canvas, sma10, DEFUALT_WIDTH, mainH, ColorUtil.COLOR_SMA10, (float) yMax, (float) yMin, DEFUALT_WIDTH / 2);
        DrawUtils.drawLineWithXOffset(canvas, sma20, DEFUALT_WIDTH, mainH, ColorUtil.COLOR_SMA20, (float) yMax, (float) yMin, DEFUALT_WIDTH / 2);
    }

    @Override
    protected void drawText(Canvas canvas) {
        if(data == null || data.size() == 0) return;
        //4，画X轴时间
        if(showList.size() <= drawCount) {
            DrawUtils.drawKLineXTime(canvas, showList.get(0).getTime(), showList.get(showList.size() - 1).getTime(), mWidth, mainH);
        } else {
            DrawUtils.drawKLineXTime(canvas, showList.get(0).getTime(), null, mWidth, mainH);
        }
        //5，画Y轴价格
        DrawUtils.drawKLineYPrice(canvas, yMax, yMin, mainH);
    }

    @Override
    protected void drawVOL(Canvas canvas) {
        if(data == null || data.size() == 0) return;
        long max = 0;
        for(StickData data : showList) {
            max = data.getCount() > max ? data.getCount() : max;
        }
        //如果量全为0，则不画
        if(max == 0) return;
        //2,画量线，多条竖直线
        DrawUtils.drawVOLRects(canvas, xUnit,indexStartY, indexH, max, showList);
        //3,画量的sma5,sma10
        drawCountSma(canvas, (float) max);
    }

    @Override
    protected void drawZJ(Canvas canvas) {

    }

    @Override
    protected void init() {
        if(data == null) return;
        drawCount = (int) (mWidth / DEFUALT_WIDTH);
        candleXDistance = drawCount * WIDTH_SCALE;

        LogUtils.e("drawCount=="+drawCount+"==candleXDistance=="+candleXDistance);
        if(data != null && data.size() > 0) {
            if(drawCount < data.size()) {
                getShowList(offset);
            } else {
                showList = new ArrayList<>();
                showList.addAll(data);
            }
        }
        if(showList == null) return;

        float[] low = new float[showList.size()];
        float[] high = new float[showList.size()];
        int i = 0;
        for(StickData d : showList) {
            low[i] = (float) d.getLow();
            high[i] = (float) d.getHigh();
            i++;
        }
        float[] maxAndMin = LineUtil.getMaxAndMin(low, high);
        yMax = maxAndMin[0];
        yMin = maxAndMin[1];

        yUnit = (float) (yMax - yMin) / mainH;
        xUnit = mWidth / drawCount;
    }

    @Override
    protected void drawCandles(Canvas canvas) {
        if(data == null || data.size() == 0) return;
        float x = 0;
        if(showList == null || showList.size() == 0) return;
        //计算出页面能显示多少个
        for(int i = 0; i < showList.size(); i++) {
            if(drawCount < data.size()) {
                x = mWidth - (mWidth / drawCount * (showList.size() - i));
            } else {
                x = (mWidth / drawCount *i);
            }

            DrawUtils.drawCandle(canvas,
                    parseNumber(showList.get(i).getHigh()),
                    parseNumber(showList.get(i).getLow()),
                    parseNumber(showList.get(i).getOpen()),
                    parseNumber(showList.get(i).getClose()),
                    x,
                    parseNumber(showList.get(i).getHigh()),
                    candleXDistance,
                    mWidth);
        }
    }


    /**
     * 画量的均线
     * @param canvas
     * @param max
     */
    private void drawCountSma(Canvas canvas, float max) {
        if(data == null || data.size() == 0) return;
        float[] sma5 = new float[showList.size()];
        float[] sma10 = new float[showList.size()];
        int size = showList.size();
        for (int i = 0; i < showList.size(); i++) {
            if(size > IndexParseUtil.START_SMA5)
                sma5[i] = (float) showList.get(i).getCountSma5();
            if(size > IndexParseUtil.START_SMA10)
                sma10[i] = (float) showList.get(i).getCountSma10();
        }
        DrawUtils.drawLines(canvas, sma5, DEFUALT_WIDTH, indexH - 2, ColorUtil.COLOR_SMA5, max, 0f, false, indexStartY + 2, DEFUALT_WIDTH / 2);
        DrawUtils.drawLines(canvas, sma10, DEFUALT_WIDTH, indexH - 2, ColorUtil.COLOR_SMA10, max, 0f, false, indexStartY + 2, DEFUALT_WIDTH / 2);
    }

    public void setDataAndInvalidate(ArrayList<StickData> data) {
        this.data = data;
        parseData();
        postInvalidate();
    }

    /**
     * 设置K线类型
     */
    public void setType(int type) {
        lineType = type;
    }

    /**
     * 计算各指标
     */
    private void parseData() {
        offset = 0;
        //根据当前显示的指标类型，优先计算指标
        IndexParseUtil.initSma(this.data);

        //把暂时不显示的计算，放在线程中去完成，避免阻塞主线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                switch (indexType) {
                    case ChartConstant.INDEX_VOL:
                        IndexParseUtil.initMACD(data);
                        IndexParseUtil.initKDJ(data);
                        break;
                    case  ChartConstant.INDEX_MACD:
                        IndexParseUtil.initKDJ(data);
                        break;
                    case  ChartConstant.INDEX_KDJ:
                        IndexParseUtil.initMACD(data);
                        break;
                }
            }
        }).start();
    }


    /**
     * 获取页面一页可展示的数据
     */
    private void getShowList(int offset) {
        if(offset != 0 && data.size() - drawCount - offset < 0) {
            offset = data.size() - drawCount;
        }
        showList = new ArrayList<>();
        showList.addAll(data.subList(data.size() - drawCount - offset, data.size() - offset));
    }


    /**
     * 把传入的参数计算成坐标，直接展示到界面上
     * @param input
     * @return 返回里面的StickData的最高价最低价，都是可以直接显示在坐标上的
     */
    private float parseNumber(double input) {
        return mainH - (float)(( input - yMin) / yUnit);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(mScaleGestureDetector != null)
            mScaleGestureDetector.onTouchEvent(event);
        if(gestureDetector!=null){
            gestureDetector.onTouchEvent(event);
        }
        return true;
        /*if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();//获得VelocityTracker类实例
        }
        mVelocityTracker.addMovement(event);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                mVelocityTracker.clear();

                mLastX = event.getX();
                return true;
            case MotionEvent.ACTION_MOVE:


                float x = event.getX();
                float delX = x - mLastX;

                scrollBy(-(int) delX, 0);

                mLastX = x;
                return true;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:

                final VelocityTracker velocityTracker = mVelocityTracker;
                // 1000 provides pixels per second
                // 设置maxVelocity值为0.01时，速率大于0.01时，显示的速率都是0.01,速率小于0.01时，显示正常
                velocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
                float xVelocity = velocityTracker.getXVelocity();
                if (Math.abs(xVelocity) >= mMinVelocity) {
                    fling(-(int) xVelocity);
                } else {
                    //scrollExactly();
                }

                velocityTracker.clear();

                return true;

        }
        return true;*/
    }

    private ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener(){
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            if(data == null) return super.onScale(detector);
            //放大是由1变大，缩小是由1变小
            float scale = detector.getScaleFactor();
            //这个变化太快，把scale变慢一点
            scale = 1 + ((scale - 1) * 0.4f);
            drawCount = (int) (mWidth / DEFUALT_WIDTH);
            if(scale < 1 && drawCount >= data.size()) {

            }else if(scale > 1 && drawCount < 50) {
                //放大时，当一屏少于20个时，则不再放大
            }else {
                DEFUALT_WIDTH = DEFUALT_WIDTH * scale;
                invalidate();
            }

            return super.onScale(detector);
        }
    });


    //点击手势监听
    protected GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return onViewScroll(e1, e2, distanceX, distanceY);
        }
    });

    protected boolean onViewScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if(data != null && drawCount < data.size() && Math.abs(distanceX) > DEFUALT_WIDTH) {
            int temp = offset + (int)(0 - distanceX / DEFUALT_WIDTH);
            if(temp < 0 || temp + drawCount > data.size()) {

            } else {
                offset = temp;
                postInvalidate();
            }
            return true;
        }
        return false;
    }

    public void fling(int velocityX) {
        mScroller.fling(getScrollX(), getScrollY(), velocityX, 0, mMinScrollX, mMaxScrollX, 0,0);
    }
}
